package ru.surfstudio.graduate.activity;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import ru.surfstudio.graduate.R;
import ru.surfstudio.graduate.bean.ChannelManager;
import ru.surfstudio.graduate.data.Channel;
import ru.surfstudio.graduate.data.Channel.Mark;
import ru.surfstudio.graduate.handler.FeedsAddHandler;
import ru.surfstudio.graduate.service.HttpService;
import ru.surfstudio.graduate.task.FeedSearchTask;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Messenger;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AbstractRssActivity {
	
	private static final String TAG = "MainActivity";

	private static final int DIALOG_REMOVE = 0x2;
	
	private static final String POSITION_DEL = "POSITION_DEL";
	
	private static final int DEFAULT_CHANNEL_COUNT = 2;
	
	private ListView channelListView;
	
	private ChannelAdapter adapter;
	
	private List<Channel> channelList;
	
	private MainActivityState state;
	
	/** Запоминаем номер строки(позицию channel), кот. нужно удалить */
	private int positionDel;
	
	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
        
        Log.d(TAG, ">>> START ACTIVITY");
        state = (MainActivityState) getLastNonConfigurationInstance();
		if (state == null) {
			Log.d(TAG, ">>> create state");
			state = new MainActivityState(this);
		} else {
			state.attach(this);
		}
		
		channelList = new ArrayList<Channel>();
        adapter = new ChannelAdapter(channelList); 
        
        channelListView = (ListView) findViewById(R.id.main_channels_list);
        channelListView.setAdapter(adapter);
        channelListView.setOnItemClickListener(onListClick);
        registerForContextMenu(channelListView);
    }
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		
		state.detach();
	}
	
	@Override
	public void onStart() {
		super.onStart();
	
		executeLoadChannelTask();
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		outState.putInt(POSITION_DEL, positionDel);
	}
	
	@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);
		positionDel = savedInstanceState.getInt(POSITION_DEL);
	}
	
	@Override
    public Object onRetainNonConfigurationInstance() {
        state.detach();
        return state;
    }
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		new MenuInflater(this).inflate(R.menu.main_option, menu);
		return super.onCreateOptionsMenu(menu);
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		
		switch (item.getItemId()) {
			case R.id.main_subscribe_menu_item:
				startActivity(new Intent(this, SearchChannelActivity.class));
				return true;
			case R.id.main_search_menu_item:
				// TODO Auto-generated method stub
				return true;
			case R.id.main_update_menu_item:
				startUpdateChannel();
				return true;
		}
		return super.onOptionsItemSelected(item);
	}
	
	@Override
	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
		new MenuInflater(this).inflate(R.menu.main_context, menu);
	}
	
	@Override
	public boolean onContextItemSelected(MenuItem item) {
		AdapterView.AdapterContextMenuInfo info = 
			(AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
		
		switch (item.getItemId()) {
			case R.id.main_remove_menu_item:
				positionDel = info.position;
				showDialog(DIALOG_REMOVE);
				return true;
		}
		return super.onContextItemSelected(item);
	}
	
	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
			case DIALOG_REMOVE:
				return createRemovingDialog();
		}
		return super.onCreateDialog(id);
	}
	
	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		
		switch (id) {
			case DIALOG_REMOVE:
				((AlertDialog) dialog).setMessage(getRemovingDialogMess(positionDel));
				break;
		}
	}
	
	@Override
	public void onPostFeedsUpdate(Channel channel) {
		Log.d(TAG, "onPostFeedsUpdate");
		if (channel.getUrl().equals(channelList.get(channelList.size() - 1).getUrl())) {
			Log.d(TAG, "UDATE CHANNELS IS DONE");
			executeLoadChannelTask();
		}
	}
	
	/** Генерируем диалог для удаления channel */
	private Dialog createRemovingDialog() {
		
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(R.string.main_remove_dialog_title)
			.setMessage(getRemovingDialogMess(positionDel))
			.setPositiveButton(R.string.ok, 
					new DialogInterface.OnClickListener() {
			
				@Override
				public void onClick(DialogInterface dialog, int which) {
					state.removeChannelTask = new RemoveChannelTask(MainActivity.this);
					state.removeChannelTask.execute(positionDel);
				}
			}).setNegativeButton(R.string.cancel, null);
		
		return builder.create();
	}
	
	/** Генерируем текст диалога для удаления channel */
	// Проверяем, что adapter не пуст, т.к. вызов метода onCreateDialog(int) 
	// может произойти раньше заполнения adapter
	private String getRemovingDialogMess(int position) {
		String name = "";
		if (!adapter.isEmpty())
			name = adapter.getItem(position).getName();
		return String.format(getString(R.string.main_remove_dialog_text), name);
	}
	
	private void executeLoadChannelTask() {
		Log.d(TAG, ">>> loadChannelTask execute");
		if (state.loadChannelTask == null || state.loadChannelTask.isCancelled() ||
				state.loadChannelTask.getStatus().equals(AsyncTask.Status.FINISHED)) {
			
			state.loadChannelTask = new LoadChannelTask(this);
			state.loadChannelTask.execute();
		}
	}
	
	private void startUpdateChannel() {
		for (int i = DEFAULT_CHANNEL_COUNT; i < adapter.getCount(); i++) {
			Intent intent = new Intent(this, HttpService.class);
			intent.putExtra(HttpService.MARK_TASK, new FeedSearchTask(adapter.getItem(i)));
			intent.putExtra(HttpService.MARK_HANDLER, new Messenger(state.handler));
			startService(intent);
		}
	}
	
	
	private AdapterView.OnItemClickListener onListClick = new AdapterView.OnItemClickListener() {

		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
			Intent intent = new Intent(MainActivity.this, FeedListActivity.class);
			intent.putExtra(FeedListActivity.MARK_CHANNEL, adapter.getItem(position));
			startActivity(intent);
		}
		
	};
	
	
	private class ChannelAdapter extends ArrayAdapter<Channel> {

		public ChannelAdapter(List<Channel> items) {
			super(MainActivity.this, R.layout.main_list_item, items);
		}
		
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View row = convertView;
			if (row == null) {
				row = getLayoutInflater().inflate(R.layout.main_list_item, null);
			}
			
			ViewHolder holder = (ViewHolder) row.getTag();
			if (holder == null) {
				holder = new ViewHolder(row);
				row.setTag(holder);
			}
			
			Channel channel = getItem(position);
			
			switch (channel.getMark()) {
				case ALL:
					holder.iconView.setImageDrawable(getResources().getDrawable(
							R.drawable.folder));
					holder.dateView.setText("");
					break;
				case FAVORITE:
					holder.iconView.setImageDrawable(getResources().getDrawable(
							R.drawable.star));
					holder.dateView.setText("");
					break;
				case NONE:
					holder.iconView.setImageDrawable(getResources().getDrawable(
							R.drawable.rss_big));
					if (channel.getUpdateDate() != null)
						holder.dateView.setText(prepareDate(channel.getUpdateDate()));
					break;
			}
			holder.nameView.setText(channel.getName());
			holder.countView.setText(String.valueOf(channel.getCount()));
			
			return row;
		}
		
		private String prepareDate(Date date) {
			Calendar dateCal = Calendar.getInstance();
			Calendar nowCal = Calendar.getInstance();
			dateCal.setTime(date);
			
			if (dateCal.get(Calendar.YEAR) == nowCal.get(Calendar.YEAR) &&
					dateCal.get(Calendar.DAY_OF_YEAR) == nowCal.get(Calendar.DAY_OF_YEAR)) {
				
				return String.format(getString(R.string.main_list_item_date_lable), 
						getString(R.string.main_list_item_date_now_lable),
						formatDate("HH:mm", date));
				
			} else {
				return String.format(getString(R.string.main_list_item_date_lable), 
						"", formatDate("dd.MM.yy", date));
			}
		}
		
		private String formatDate(String formatStr, Date date) {
			SimpleDateFormat format = new SimpleDateFormat(formatStr);
			return format.format(date);
		}
		
		
		private class ViewHolder {
			
			ImageView iconView = null;
			TextView nameView = null;
			TextView dateView = null;
			TextView countView = null;
			  
			ViewHolder(View row) {
				iconView = (ImageView) row.findViewById(R.id.main_list_item_image);
				nameView = (TextView) row.findViewById(R.id.main_list_item_name_text);
				dateView = (TextView) row.findViewById(R.id.main_list_item_date_text);
				countView = (TextView) row.findViewById(R.id.main_list_item_count_text);
			}
		}

	}
	
	private class LoadChannelTask extends AsyncTask<Void, Void, List<Channel>> {
		
		private MainActivity activity;
		
		public LoadChannelTask(MainActivity activity) {
			attach(activity);
		}
		
		@Override
		protected List<Channel> doInBackground(Void... params) {
			Log.d(TAG, ">>> loadChannelTask doInBackground()");
			List<Channel> listChanenl = null;
			if (activity != null) {
				try {
					ChannelManager channelManager = new ChannelManager(activity.getHelper());
					channelManager.createDefaultChannels(activity.getResources());
					listChanenl = channelManager.getAllChannels();
						
				} catch (SQLException e) {
					Log.e(TAG, e.getMessage(), e);
				} catch (Exception e) {
					Log.e(TAG, e.getMessage(), e);
				}
			}
			return listChanenl;
		}
		
		@Override
		protected void onPostExecute(List<Channel> list) {
			if (activity != null) {
				
				if (list != null && list.size() != 0) {
					activity.channelList.clear();
					activity.channelList.addAll(list);
					activity.adapter.notifyDataSetChanged();
				} else {
					Toast.makeText(activity, R.string.database_error, Toast.LENGTH_LONG)
						.show();
					Log.w(TAG, getString(R.string.database_error));
				}
			}
		}
		
		public void detach() {
			activity = null;
		}
		
		public void attach(MainActivity activity) {
			this.activity = activity;
		}
		
	}
	
	
	private class RemoveChannelTask extends AsyncTask<Integer, Integer, Channel> {

		private MainActivity activity;
		
		public RemoveChannelTask(MainActivity activity) {
			attach(activity);
		}
		
		@Override
		protected void onPreExecute() {
			showDialog(MainActivity.DIALOG_WAIT);
		}
		
		@Override
		protected Channel doInBackground(Integer... params) {
			Channel channel = adapter.getItem(params[0]);
			if (channel.getMark() != Mark.NONE)
				return null;
			
			try {
				if (activity != null) {
					ChannelManager channelManager = new ChannelManager(activity.getHelper());
					channelManager.removeChannelWithFeeds(channel);
					channelManager.setCountToDefaultChannels();
					
					publishProgress(channelManager.getChannelAll().getCount(), 
							channelManager.getChannelFavorite().getCount());
				}
				return channel;
				
			} catch (SQLException e) {
				Log.e(TAG, e.getMessage(), e);
			} catch (Exception e) {
				Log.e(TAG, e.getMessage(), e);
			}
			return null;
		}
		
		@Override
		protected void onProgressUpdate(Integer... val) {
			if (activity != null && activity.channelList.size() >= 2 && val.length == 2) {
				activity.channelList.get(0).setCount(val[0]);
				activity.channelList.get(1).setCount(val[1]);
			}
		}
		
		@Override
		protected void onPostExecute(Channel channel) {
			if (activity != null) {
				activity.dismissDialog(MainActivity.DIALOG_WAIT);
				if (channel == null) {
					Toast.makeText(activity, R.string.database_error, Toast.LENGTH_LONG).show();
					Log.w(TAG, getString(R.string.database_error));
				}
				else {
					activity.channelList.remove(channel);
					
					activity.adapter.notifyDataSetChanged();
					activity.positionDel = 0;
				}
			}
		}
		
		public void detach() {
			activity = null;
		}
		
		public void attach(MainActivity activity) {
			this.activity = activity;
		}
		
	}
	
	/** Activity state */
    private static class MainActivityState {

        public RemoveChannelTask removeChannelTask;
        
        public LoadChannelTask loadChannelTask;
        
        public FeedsAddHandler handler;
        
        public MainActivityState(MainActivity activity) {
        	if (handler == null) {
        		handler = new FeedsAddHandler(activity);
        	}
        }
        
        public void detach() {
        	if (removeChannelTask != null)
        		removeChannelTask.detach();
        	if (loadChannelTask != null) {
        		Log.d(TAG, ">>> detach loadChannelTask");
        		loadChannelTask.detach();
        	}
        	if (handler != null)
        		handler.detach();
        }
        
        public void attach(MainActivity activity) {
        	if (removeChannelTask != null)
        		removeChannelTask.attach(activity);
        	if (loadChannelTask != null) {
        		Log.d(TAG, ">>> attach loadChannelTask");
        		loadChannelTask.attach(activity);
        	}
        	if (handler != null)
        		handler.attach(activity);
        }
        
    }

}